home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / corelib / ncbimisc.c < prev    next >
Text File  |  1996-07-05  |  24KB  |  908 lines

  1. /*   ncbimisc.c
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:  ncbimisc.c
  27. *
  28. * Author:  Gish, Kans, Ostell, Schuler
  29. *
  30. * Version Creation Date:   10/23/91
  31. *
  32. * $Revision: 2.11 $
  33. *
  34. * File Description: 
  35. *       miscellaneous functions
  36. *
  37. * Modifications:  
  38. * --------------------------------------------------------------------------
  39. * Date     Name        Description of modification
  40. * -------  ----------  -----------------------------------------------------
  41. * 04-15-93 Schuler     Changed _cdecl to LIBCALL
  42. * 06-15-93 Schuler     SGML functions moved to ncbisgml.c
  43. * 02-16-94 Epstein     Retired Gestalt functions and definitions
  44. *
  45. * ==========================================================================
  46. */
  47.  
  48. #include <ncbi.h>
  49. #include <ncbiwin.h>
  50.  
  51. /*
  52. TRIPLE_MARK is the character inserted before the thousands, millions,
  53. billions, etc. digit positions.  Change TRIPLE_MARK to a period
  54. for the International scene, or define it as '\0' if no magnitude
  55. markers are desired.
  56. */
  57. #define TRIPLE_MARK    ','
  58.  
  59. #define MISC_COMMAS 1 /* insert commas only when |value| >= 10,000 */
  60. #define MISC_ALLCOMMAS 2 /* insert commas for any |value| >= 1,000 */
  61. #define MISC_ANYCOMMAS (MISC_COMMAS|MISC_ALLCOMMAS)
  62. #define MISC_PLUSSIGNS 4 /* prepend a plus sign (+) to positive values */
  63.  
  64.  
  65. /*
  66. buf[NBUFS][] is a circularly-maintained list of buffers for storing
  67. the results of calls to Nlm_Ltostr() and Nlm_Ultostr().  Up to NBUFS
  68. usages of either function in a single printf() may be made.
  69. NBUFS should be defined large enough to satisfy _all_ likely occurrences.
  70. */
  71. #define NBUFS 10 /* No. of static buffers for the ASCII results */
  72.  
  73. static int    bufno = 0; /* current buffer marker in the circular list */
  74. static char    buf[NBUFS][(CHAR_BIT)*sizeof(long)/2];
  75.  
  76. /* divray[] is a fixed array of power-of-10 divisors which must be initialized*/
  77. static unsigned long divray[CHAR_BIT*sizeof(unsigned long)/2];
  78. /* divray_max is related to the maximum precision available in a long int */
  79. static int    divray_max;
  80.  
  81. /* commaray[] is a fixed array that identifies positions where commas belong */
  82. static char    commaray[DIM(divray)];
  83.  
  84. /* divray_init() initializes divray[] */
  85. static void divray_init PROTO((void));
  86.  
  87. /* ultostr() is the basic (unsigned) integer-to-ASCII conversion engine */
  88. static void ultostr PROTO((char *buf, unsigned long value, int commas));
  89.  
  90. /* ulwidth() is the basic length-determiner for integer-ASCII conversions */
  91. static int ulwidth PROTO((unsigned long value, int commas));
  92.  
  93. /* heapify() is the basic heap-sort function used by Nlm_HeapSort() */
  94. static void    heapify PROTO((Nlm_CharPtr b0, Nlm_CharPtr b, Nlm_CharPtr lim, Nlm_CharPtr last, Nlm_sizeT w, int (LIBCALLBACK *compar) (Nlm_VoidPtr, Nlm_VoidPtr) ));
  95.  
  96. /* divray_init -- initialize array of divisors and array of marker locations */
  97. static void
  98. divray_init (void)
  99.  
  100. {
  101.     unsigned long    j = ULONG_MAX, k = 1;
  102.  
  103.     for (divray_max=0; divray_max < DIM(divray) && j != 0; ++divray_max) {
  104.         divray[divray_max] = k;
  105.         if ((divray_max+1)%3 == 0)
  106.             commaray[divray_max] = (TRIPLE_MARK != '\0');
  107.         j /= 10;
  108.         k *= 10;
  109.     }
  110.     --divray_max;
  111. }
  112.  
  113. /* ultostr is the basic (unsigned) integer->ASCII conversion engine */
  114. static void
  115. ultostr (char *buf, unsigned long value, int commas)
  116.  
  117. {
  118.     unsigned long    value_orig = value;
  119.     int    i, quotient;
  120.  
  121.     if (divray_max == 0)
  122.         divray_init();
  123.  
  124.     /*
  125.     Insert commas when value_orig >= 10000 (the Macintosh Way),
  126.     unless MISC_ALLCOMMAS is set.
  127.     */
  128.     commas = ((commas&MISC_ALLCOMMAS) && value >= 1000)
  129.                 || (commas && value > (10*1000));
  130.  
  131.     for (i=divray_max; i > 0 && divray[i] > value; --i)
  132.         ;
  133.  
  134.     for (; i >= 0; --i) {
  135.         if (commas && commaray[i] != NULLB && value != value_orig)
  136.             *buf++ = TRIPLE_MARK;
  137.         quotient = (int)(value / divray[i]);
  138.         *buf++ = (char) '0' + (char) quotient;
  139.         switch (quotient) {
  140.         case 0: break;
  141.         case 1: value -=   divray[i]; break;
  142.         case 2: value -= 2*divray[i]; break;
  143.         case 3: value -= 3*divray[i]; break;
  144.         case 4: value -= 4*divray[i]; break;
  145.         case 5: value -= 5*divray[i]; break;
  146.         case 6: value -= 6*divray[i]; break;
  147.         case 7: value -= 7*divray[i]; break;
  148.         case 8: value -= 8*divray[i]; break;
  149.         case 9: value -= 9*divray[i]; break;
  150.         default: value -= quotient*divray[i]; break; /* shouldn't be taken */
  151.         }
  152.     }
  153.     *buf = NULLB; /* tack on a NUL terminator */
  154.     return;
  155. }
  156.  
  157. /* Nlm_Ltostr -- convert a signed long integer to ASCII */
  158. char * LIBCALL
  159. Nlm_Ltostr (long value, int opts)
  160.  
  161. {
  162.     char    *bp0, *bp;
  163.  
  164.     bp0 = bp = &buf[bufno][0];
  165.     if (++bufno >= NBUFS)
  166.         bufno = 0;
  167.  
  168.     if (value < 0) {
  169.         *bp++ = '-';
  170.         value = -value;
  171.     }
  172.     else
  173.         if (opts&MISC_PLUSSIGNS && value > 0)
  174.             *bp++ = '+';
  175.  
  176.     ultostr(bp, (unsigned long)value, opts&MISC_ANYCOMMAS);
  177.  
  178.     return bp0;
  179. }
  180.  
  181. /* Nlm_Ultostr convert an unsigned long integer to ASCII */
  182. char * LIBCALL
  183. Nlm_Ultostr (unsigned long value, int opts)
  184.  
  185. {
  186.     char    *bp0, *bp;
  187.  
  188.     bp = bp0 = &buf[bufno][0];
  189.     if (++bufno >= NBUFS)
  190.         bufno = 0;
  191.  
  192.     if (opts&MISC_PLUSSIGNS && value > 0)
  193.         *bp++ = '+';
  194.  
  195.     ultostr(bp, value, opts&MISC_ANYCOMMAS);
  196.  
  197.     return bp0;
  198. }
  199.  
  200. /*
  201. Return the length (in characters) of the ASCII base 10 representation
  202. of the specified integer.
  203.  
  204. If "opts&MISC_COMMAS" is non-zero, consider the additional length required
  205. for commas before the thousands, millions, billions, etc.  positions.
  206.  
  207. If "opts&MISC_ALLCOMMAS" is non-zero, insert commas even when the value
  208. of the integer is less than 10,000.
  209.  
  210. If "opts&MISC_PLUSSIGNS" is non-zero, consider the length of a plus sign
  211. in front of any positive value, as well as the standard minus sign in front
  212. of negative values.
  213. */
  214. int LIBCALL
  215. Nlm_Lwidth (long value, int opts)
  216.  
  217. {
  218.     int    len;
  219.  
  220.     if (value < 0) {
  221.         len = 1; /* account for the minus sign */
  222.         value = -value;
  223.     }
  224.     else
  225.         /* account for a plus sign */
  226.         len = (opts&MISC_PLUSSIGNS) && (value > 0);
  227.             
  228.     return len + ulwidth(value, opts&MISC_ANYCOMMAS);
  229. }
  230.  
  231. /*
  232. Return the length (in characters) of the ASCII base 10 representation
  233. of the specified unsigned integer.
  234. */
  235. int LIBCALL
  236. Nlm_Ulwidth (unsigned long value, int opts)
  237.  
  238. {
  239.     int    len;
  240.  
  241.     len = ulwidth(value, opts&MISC_ANYCOMMAS);
  242.     return len + ((opts&MISC_PLUSSIGNS) && (value > 0));
  243. }
  244.  
  245. static int
  246. ulwidth (unsigned long value, int commas)
  247.  
  248. {
  249.     int    j, len;
  250.  
  251.     if (divray_max == 0)
  252.         divray_init();
  253.  
  254.     for (len=divray_max; len > 0 && divray[len] > value; --len)
  255.         ;
  256.  
  257.     if ((commas&MISC_ALLCOMMAS) || (commas && value >= (10*1000)) ) {
  258.         for (j = len-1; j > 1; --j)
  259.             len += (commaray[j] != 0);
  260.     }
  261.     return len+1;
  262. }
  263.  
  264. /*
  265.     Nlm_HeapSort -- sort a list using an heap sort algorithm
  266.  
  267.     Performance is guaranteed O(NlogN).  Compared to BSD UNIX(TM) qsort,
  268.     Nlm_HeapSort averages about half as fast--which may be acceptable
  269.     for a portable, public domain function which qsort is not.
  270.  
  271.     This code was derived from original work by Professor Webb Miller
  272.     (Penn. State University), but don't blame him for this mess or any errors.
  273.  
  274.     7/31/90 WRG
  275.     6/18/92 Modified for segmented memory safety.  JMO
  276. */
  277.  
  278. void LIBCALL
  279. Nlm_HeapSort (Nlm_VoidPtr b, Nlm_sizeT nel, Nlm_sizeT width, int (LIBCALLBACK *compar )PROTO ((Nlm_VoidPtr, Nlm_VoidPtr )))    /* Element comparison routine */
  280.  
  281. {
  282.     register Nlm_CharPtr    base = (Nlm_CharPtr)b;
  283.     register Nlm_sizeT    i;
  284.     register char    ch;
  285.     register Nlm_CharPtr     base0 = (Nlm_CharPtr)base, lim, basef;
  286.  
  287.     if (nel < 2)
  288.         return;
  289.  
  290.     lim = &base[((nel-2)/2)*width];
  291.     basef = &base[(nel-1)*width];
  292.     i = nel/2;
  293.     for (base = &base0[(i - 1)*width]; i > 0; base = base - width) {
  294.         heapify(base0, base, lim, basef, width, compar);
  295.         i--;
  296.     }
  297.  
  298.     for (base = &base0[(nel-1)*width]; base > base0; base -= width) {
  299.         for (i=0; i<width; ++i) {
  300.             ch = base0[i];
  301.             base0[i] = base[i];
  302.             base[i] = ch;
  303.         }
  304.         lim = base0 + ((base-base0)/2 - width);
  305.         if (base > base0+width)
  306.             heapify(base0, base0, lim, base-width, width, compar);
  307.     }
  308. }
  309.  
  310. static void
  311. heapify (Nlm_CharPtr base0, Nlm_CharPtr base, Nlm_CharPtr lim, Nlm_CharPtr last, Nlm_sizeT width, int (LIBCALLBACK *compar )PROTO ((Nlm_VoidPtr, Nlm_VoidPtr )))
  312.  
  313. {
  314.     register Nlm_sizeT    i;
  315.     register char    ch;
  316.     register Nlm_CharPtr left_son, large_son;
  317.  
  318.     left_son = base0 + 2*(base-base0) + width;
  319.     while (base <= lim) {
  320.         if (left_son == last)
  321.             large_son = left_son;
  322.         else
  323.             large_son = (*compar)(left_son, left_son+width) >= 0 ?
  324.                             left_son : left_son+width;
  325.         if ((*compar)(base, large_son) < 0) {
  326.             for (i=0; i<width; ++i) {
  327.                 ch = base[i];
  328.                 base[i] = large_son[i];
  329.                 large_son[i] = ch;
  330.             }
  331.             base = large_son;
  332.             left_son = base0 + 2*(base-base0) + width;
  333.         } else
  334.             break;
  335.     }
  336. }
  337.  
  338. /*****************************************************************************
  339. *
  340. *   ValNodeNew(vnp)
  341. *      adds after last node in list if vnp not NULL
  342. *
  343. *****************************************************************************/
  344. ValNodePtr LIBCALL ValNodeNew (ValNodePtr vnp)
  345.  
  346. {
  347.     ValNodePtr newnode;
  348.  
  349.     newnode = (ValNodePtr) Nlm_MemNew(sizeof(ValNode));
  350.     if (vnp != NULL)
  351.     {
  352.         while (vnp->next != NULL)
  353.             vnp = vnp->next;
  354.         vnp->next = newnode;
  355.     }
  356.     return newnode;
  357. }
  358.  
  359. /*****************************************************************************
  360. *
  361. *   ValNodeAdd(head)
  362. *      adds after last node in list if *head not NULL
  363. *      If *head is NULL, sets it to the new ValNode
  364. *      returns pointer to the NEW node added
  365. *
  366. *****************************************************************************/
  367. ValNodePtr LIBCALL ValNodeAdd (ValNodePtr PNTR head)
  368.  
  369. {
  370.     ValNodePtr newnode;
  371.  
  372.     if (head != NULL)
  373.     {
  374.         newnode = ValNodeNew(*head);
  375.         if (*head == NULL)
  376.             *head = newnode;
  377.     }
  378.     else
  379.         newnode = ValNodeNew(NULL);
  380.  
  381.     return newnode;
  382. }
  383.  
  384. /*****************************************************************************
  385. *
  386. *   ValNodeLink(head, newnode)
  387. *      adds newnode at end of chain
  388. *      if (*head == NULL) *head = newnode
  389. *      ALWAYS returns pointer to START of chain
  390. *
  391. *****************************************************************************/
  392. ValNodePtr LIBCALL ValNodeLink (ValNodePtr PNTR head, ValNodePtr newnode)
  393. {
  394.    ValNodePtr vnp;
  395.  
  396.    if (head == NULL)
  397.      return newnode;
  398.  
  399.    vnp = *head;
  400.    
  401.    if (vnp != NULL )
  402.    {
  403.         while (vnp->next != NULL)
  404.             vnp = vnp->next;
  405.         vnp->next = newnode;
  406.     }
  407.     else
  408.         *head = newnode;
  409.  
  410.    return *head;
  411. }
  412.  
  413. /*****************************************************************************
  414. *
  415. *   ValNodeAddStr (head, choice, str)
  416. *      adds like ValNodeAdd()
  417. *      sets newnode->choice = choice (if choice does not matter, use 0)
  418. *      sets newnode->data.ptrvalue = str
  419. *         does NOT copy str
  420. *      if str == NULL, does not add a ValNode
  421. *   
  422. *****************************************************************************/
  423. ValNodePtr LIBCALL ValNodeAddStr (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_CharPtr str)
  424. {
  425.     ValNodePtr newnode;
  426.  
  427.     if (str == NULL) return NULL;
  428.  
  429.     newnode = ValNodeAdd(head);
  430.     if (newnode != NULL)
  431.     {
  432.         newnode->choice = (Nlm_Uint1)choice;
  433.         newnode->data.ptrvalue = (Nlm_VoidPtr)str;
  434.     }
  435.  
  436.     return newnode;
  437. }
  438.  
  439. /*****************************************************************************
  440. *
  441. *   ValNodeCopyStr (head, choice, str)
  442. *      adds like ValNodeAdd()
  443. *      sets newnode->choice = choice (if choice does not matter, use 0)
  444. *      sets newnode->data.ptrvalue = str
  445. *         makes a COPY of str
  446. *      if str == NULL, does not add a ValNode
  447. *
  448. *****************************************************************************/
  449. ValNodePtr LIBCALL ValNodeCopyStr (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_CharPtr str)
  450. {
  451.     ValNodePtr newnode;
  452.  
  453.     if (str == NULL) return NULL;
  454.  
  455.     newnode = ValNodeAdd(head);
  456.     if (newnode != NULL)
  457.     {
  458.         newnode->choice = (Nlm_Uint1)choice;
  459.         newnode->data.ptrvalue = StringSave(str);
  460.     }
  461.  
  462.     return newnode;
  463. }
  464.  
  465. /*****************************************************************************
  466. *
  467. *   ValNodeAddInt (head, choice, value)
  468. *      adds like ValNodeAdd()
  469. *      sets newnode->choice = choice (if choice does not matter, use 0)
  470. *      sets newnode->data.intvalue = value
  471. *   
  472. *****************************************************************************/
  473. ValNodePtr LIBCALL ValNodeAddInt (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_Int4 value)
  474. {
  475.     ValNodePtr newnode;
  476.  
  477.     newnode = ValNodeAdd(head);
  478.     if (newnode != NULL)
  479.     {
  480.         newnode->choice = (Nlm_Uint1)choice;
  481.         newnode->data.intvalue = value;
  482.     }
  483.  
  484.     return newnode;
  485. }
  486.  
  487. /*****************************************************************************
  488. *
  489. *   ValNodeAddBoolean (head, choice, value)
  490. *      adds like ValNodeAdd()
  491. *      sets newnode->choice = choice (if choice does not matter, use 0)
  492. *      sets newnode->data.boolvalue = value
  493. *   
  494. *****************************************************************************/
  495. ValNodePtr LIBCALL ValNodeAddBoolean (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_Boolean value)
  496. {
  497.     ValNodePtr newnode;
  498.  
  499.     newnode = ValNodeAdd(head);
  500.     if (newnode != NULL)
  501.     {
  502.         newnode->choice = (Nlm_Uint1)choice;
  503.         newnode->data.boolvalue = value;
  504.     }
  505.  
  506.     return newnode;
  507. }
  508.  
  509. /*****************************************************************************
  510. *
  511. *   ValNodeAddFloat (head, choice, value)
  512. *      adds like ValNodeAdd()
  513. *      sets newnode->choice = choice (if choice does not matter, use 0)
  514. *      sets newnode->data.realvalue = value
  515. *
  516. *****************************************************************************/
  517. ValNodePtr LIBCALL ValNodeAddFloat (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_FloatHi value)
  518. {
  519.     ValNodePtr newnode;
  520.  
  521.     newnode = ValNodeAdd(head);
  522.     if (newnode != NULL)
  523.     {
  524.         newnode->choice = (Nlm_Uint1)choice;
  525.         newnode->data.realvalue = value;
  526.     }
  527.  
  528.     return newnode;
  529. }
  530.  
  531. /*****************************************************************************
  532. *
  533. *   ValNodeAddPointer (head, choice, value)
  534. *      adds like ValNodeAdd()
  535. *      sets newnode->choice = choice (if choice does not matter, use 0)
  536. *      sets newnode->data.realvalue = value
  537. *
  538. *****************************************************************************/
  539. ValNodePtr LIBCALL ValNodeAddPointer (ValNodePtr PNTR head, Nlm_Int2 choice, Nlm_VoidPtr value)
  540. {
  541.     ValNodePtr newnode;
  542.  
  543.     newnode = ValNodeAdd(head);
  544.     if (newnode != NULL)
  545.     {
  546.         newnode->choice = (Nlm_Uint1)choice;
  547.         newnode->data.ptrvalue = value;
  548.     }
  549.  
  550.     return newnode;
  551. }
  552.  
  553.  
  554. /*****************************************************************************
  555. *
  556. *   ValNodeFree(vnp)
  557. *       frees whole chain of ValNodes
  558. *       Does NOT free associated data pointers
  559. *           see ValNodeFreeData()
  560. *
  561. *****************************************************************************/
  562. ValNodePtr LIBCALL ValNodeFree (ValNodePtr vnp)
  563. {
  564.     ValNodePtr next;
  565.  
  566.     while (vnp != NULL)
  567.     {
  568.         next = vnp->next;
  569.         Nlm_MemFree(vnp);
  570.         vnp = next;
  571.     }
  572.     return NULL;
  573. }
  574.  
  575. /*****************************************************************************
  576. *
  577. *   ValNodeFreeData(vnp)
  578. *       frees whole chain of ValNodes
  579. *       frees associated data pointers - BEWARE of this if these are not
  580. *           allocated single memory block structures.
  581. *
  582. *****************************************************************************/
  583. ValNodePtr LIBCALL ValNodeFreeData (ValNodePtr vnp)
  584. {
  585.     ValNodePtr next;
  586.  
  587.     while (vnp != NULL)
  588.     {
  589.         Nlm_MemFree(vnp->data.ptrvalue);
  590.         next = vnp->next;
  591.         Nlm_MemFree(vnp);
  592.         vnp = next;
  593.     }
  594.     return NULL;
  595. }
  596.  
  597. /*****************************************************************************
  598. *
  599. *   ValNodePtr ValNodeExtract(headptr, choice)
  600. *       removes first node in chain where ->choice == choice
  601. *       rejoins chain after removing the node
  602. *       sets node->next to NULL
  603. *
  604. *****************************************************************************/
  605. ValNodePtr LIBCALL ValNodeExtract (ValNodePtr PNTR headptr, Nlm_Int2 choice)
  606. {
  607.     ValNodePtr last = NULL,
  608.         vnp = * headptr;
  609.  
  610.     while (vnp != NULL)
  611.     {
  612.         if (vnp->choice == (Nlm_Uint1)choice)
  613.         {
  614.             if (last == NULL)    /* first one */
  615.                 * headptr = vnp->next;
  616.             else
  617.                 last->next = vnp->next;
  618.  
  619.             vnp->next = NULL;
  620.             return vnp;
  621.         }
  622.         else
  623.         {
  624.             last = vnp;
  625.             vnp = vnp->next;
  626.         }
  627.     }
  628.  
  629.     return NULL;    /* not found */
  630. }
  631.  
  632. /*****************************************************************************
  633. *
  634. *   ValNodePtr ValNodeExtractList(headptr, choice)
  635. *       removes ALL nodes in chain where ->choice == choice
  636. *       rejoins chain after removing the nodes
  637. *       returns independent chain of extracted nodes
  638. *
  639. *****************************************************************************/
  640. ValNodePtr LIBCALL ValNodeExtractList (ValNodePtr PNTR headptr, Nlm_Int2 choice)
  641. {
  642.     ValNodePtr last = NULL, first = NULL, vnp;
  643.  
  644.     while ((vnp = ValNodeExtract(headptr, choice)) != NULL)
  645.     {
  646.         if (last == NULL)
  647.         {
  648.             last = vnp;
  649.             first = vnp;
  650.         }
  651.         else
  652.             last->next = vnp;
  653.         last = vnp;
  654.     }
  655.  
  656.     return first;
  657. }
  658.  
  659. /*****************************************************************************
  660. *
  661. *   ValNodeFindNext (head, curr, choice)
  662. *       Finds next ValNode with vnp->choice == choice after curr
  663. *       If curr == NULL, starts at head of list
  664. *       If choice < 0 , returns all ValNodes
  665. *       Returns NULL, when no more found
  666. *
  667. *****************************************************************************/
  668. ValNodePtr LIBCALL ValNodeFindNext (ValNodePtr head, ValNodePtr curr, Nlm_Int2 choice)
  669. {
  670.     if (head == NULL) return NULL;
  671.  
  672.     if (curr == NULL)
  673.         curr = head;
  674.     else
  675.         curr = curr->next;
  676.  
  677.     while (curr != NULL)
  678.     {
  679.         if ((choice < 0) || (curr->choice == (Nlm_Uint1)choice))
  680.             return curr;
  681.         curr = curr->next;
  682.     }
  683.  
  684.     return curr;
  685. }
  686.  
  687. /*****************************************************************************
  688. *
  689. *   Start Of Node List Functions
  690. *
  691. *****************************************************************************/
  692.  
  693. ValNodePtr LIBCALL NodeListNew (void)
  694.  
  695. {
  696.   ValNodePtr  vnp;
  697.  
  698.   vnp = ValNodeNew (NULL);
  699.   return vnp;
  700. }
  701.  
  702. ValNodePtr LIBCALL NodeListFree (ValNodePtr head)
  703.  
  704. {
  705.   if (head != NULL) {
  706.     ValNodeFreeData (head);
  707.   }
  708.   return NULL;
  709. }
  710.  
  711. Nlm_Int2 LIBCALL NodeListLen (ValNodePtr head)
  712.  
  713. {
  714.   Nlm_Int2  item;
  715.  
  716.   item = 0;
  717.   if (head != NULL) {
  718.     while (head->next != NULL) {
  719.       head = head->next;
  720.       item++;
  721.     }
  722.   }
  723.   return item;
  724. }
  725.  
  726. ValNodePtr LIBCALL NodeListFind (ValNodePtr head, Nlm_Int2 item, Nlm_Boolean extend)
  727.  
  728. {
  729.   ValNodePtr  vnp;
  730.  
  731.   vnp = NULL;
  732.   if (head != NULL && item > 0) {
  733.     vnp = head;
  734.     while (vnp->next != NULL && item > 0) {
  735.       vnp = vnp->next;
  736.       item--;
  737.     }
  738.     if (extend) {
  739.       while (item > 0) {
  740.         vnp = ValNodeNew (vnp);
  741.         item--;
  742.       }
  743.     } else if (item > 0) {
  744.       vnp = NULL;
  745.     }
  746.   }
  747.   return vnp;
  748. }
  749.  
  750. Nlm_Boolean LIBCALL NodeListRead (ValNodePtr head, Nlm_Int2 item, Nlm_VoidPtr ptr, Nlm_sizeT size)
  751.  
  752. {
  753.   Nlm_Boolean  copied;
  754.   Nlm_BytePtr  dst;
  755.   Nlm_BytePtr  src;
  756.   ValNodePtr   vnp;
  757.  
  758.   copied = FALSE;
  759.   if (head != NULL && item > 0 && ptr != NULL) {
  760.     vnp = NodeListFind (head, item, FALSE);
  761.     if (vnp != NULL && vnp->data.ptrvalue != NULL) {
  762.       dst = (Nlm_BytePtr) ptr;
  763.       src = (Nlm_BytePtr) (vnp->data.ptrvalue);
  764.       while (size > 0) {
  765.         *dst = *src;
  766.         dst++;
  767.         src++;
  768.         size--;
  769.       }
  770.       copied = TRUE;
  771.     } else {
  772.       Nlm_MemFill (ptr, 0, size);
  773.     }
  774.   }
  775.   return copied;
  776. }
  777.  
  778. static Nlm_Boolean LIBCALL Nlm_WriteToNode (ValNodePtr vnp, Nlm_VoidPtr ptr, Nlm_sizeT size)
  779.  
  780. {
  781.   Nlm_Boolean  copied;
  782.   Nlm_BytePtr  dst;
  783.   Nlm_BytePtr  src;
  784.  
  785.   copied = FALSE;
  786.   if (vnp != NULL) {
  787.     vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
  788.     if (ptr != NULL) {
  789.       vnp->data.ptrvalue = MemNew (size);
  790.       if (vnp->data.ptrvalue != NULL) {
  791.         dst = (Nlm_BytePtr) (vnp->data.ptrvalue);
  792.         src = (Nlm_BytePtr) ptr;
  793.         while (size > 0) {
  794.           *dst = *src;
  795.           dst++;
  796.           src++;
  797.           size--;
  798.         }
  799.         copied = TRUE;
  800.       }
  801.     }
  802.   }
  803.   return copied;
  804. }
  805.  
  806. Nlm_Boolean LIBCALL NodeListWrite (ValNodePtr head, Nlm_Int2 item, Nlm_VoidPtr ptr, Nlm_sizeT size)
  807.  
  808. {
  809.   Nlm_Boolean  copied;
  810.   ValNodePtr   vnp;
  811.  
  812.   copied = FALSE;
  813.   if (head != NULL && item > 0 && ptr != NULL) {
  814.     vnp = NodeListFind (head, item, TRUE);
  815.     copied = Nlm_WriteToNode (vnp, ptr, size);
  816.   }
  817.   return copied;
  818. }
  819.  
  820. Nlm_Boolean LIBCALL NodeListAppend (ValNodePtr head, Nlm_VoidPtr ptr, Nlm_sizeT size)
  821.  
  822. {
  823.   Nlm_Boolean  copied;
  824.   ValNodePtr   vnp;
  825.  
  826.   copied = FALSE;
  827.   if (head != NULL && ptr != NULL) {
  828.     vnp = ValNodeNew (head);
  829.     copied = Nlm_WriteToNode (vnp, ptr, size);
  830.   }
  831.   return copied;
  832. }
  833.  
  834. Nlm_Boolean LIBCALL NodeListInsert (ValNodePtr head, Nlm_Int2 item, Nlm_VoidPtr ptr, Nlm_sizeT size)
  835.  
  836. {
  837.   Nlm_Boolean  copied;
  838.   ValNodePtr   prev;
  839.   ValNodePtr   vnp;
  840.  
  841.   copied = FALSE;
  842.   if (head != NULL && item > 0 && ptr != NULL) {
  843.     if (item > 1) {
  844.       prev = NodeListFind (head, item - 1, FALSE);
  845.     } else {
  846.       prev = head;
  847.     }
  848.     if (prev != NULL) {
  849.       vnp = ValNodeNew (NULL);
  850.       if (vnp != NULL) {
  851.         vnp->next = prev->next;
  852.         prev->next = vnp;
  853.         copied = Nlm_WriteToNode (vnp, ptr, size);
  854.       }
  855.     }
  856.   }
  857.   return copied;
  858. }
  859.  
  860. Nlm_Boolean LIBCALL NodeListReplace (ValNodePtr head, Nlm_Int2 item, Nlm_VoidPtr ptr, Nlm_sizeT size)
  861.  
  862. {
  863.   Nlm_Boolean  copied;
  864.   ValNodePtr   vnp;
  865.  
  866.   copied = FALSE;
  867.   if (head != NULL && item > 0 && ptr != NULL) {
  868.     vnp = NodeListFind (head, item, FALSE);
  869.     copied = Nlm_WriteToNode (vnp, ptr, size);
  870.   }
  871.   return copied;
  872. }
  873.  
  874. Nlm_Boolean LIBCALL NodeListDelete (ValNodePtr head, Nlm_Int2 item)
  875.  
  876. {
  877.   Nlm_Boolean  deleted;
  878.   ValNodePtr   prev;
  879.   ValNodePtr   vnp;
  880.  
  881.   deleted = FALSE;
  882.   if (head != NULL && item > 0) {
  883.     if (item > 1) {
  884.       prev = NodeListFind (head, item - 1, FALSE);
  885.     } else {
  886.       prev = head;
  887.     }
  888.     if (prev != NULL) {
  889.       vnp = prev->next;
  890.       if (vnp != NULL) {
  891.         prev->next = vnp->next;
  892.         Nlm_MemFree (vnp->data.ptrvalue);
  893.         Nlm_MemFree (vnp);
  894.         deleted = TRUE;
  895.       }
  896.     }
  897.   }
  898.   return deleted;
  899. }
  900.  
  901.  
  902. /*****************************************************************************
  903. *
  904. *   End Of Node List Functions
  905. *
  906. *****************************************************************************/
  907.  
  908.